home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 4
/
Aminet 4 - November 1994.iso
/
aminet
/
comm
/
net
/
amitcp_ups10.lha
/
upsd.c
< prev
Wrap
C/C++ Source or Header
|
1993-10-10
|
11KB
|
509 lines
#ifndef lint
static char RCSid[] = "$Header: QD:ups/ups2/RCS/upsd.c,v 1.4 1986/11/19 15:21:52 scooter Exp alph $";
#endif
/*
* upsd - package delivery server
*
* upsd is the program that is called by inetd when a ups
* request is issued. It will read and write to standard input
* and standard output. Here is a description of the ups
* protocol:
*
* ups upsd type
*
* user_name ------> login name of package receiver String
* from_name ------> login name of package sender String
* full_name ------> full name of package sender String
* message ------> mail message to send String
* <----- 0 for OK Byte
* For each file:
* file_name ------> name of file to be delivered String
* file_size ------> size of file in bytes Long
* <----- 0 for OK Byte
* file ------> file size bytes
* <----- 0 for OK Byte
* file_mode ------> file mode Int
* <----- 0 for OK Byte
*
* When its all done:
* complete ------> We're done ('-Done-') String
* <----- 0 for OK Byte
*
* $Author: scooter $
* $Revision: 1.4 $
* $Date: 1986/11/19 15:21:52 $
*
* $Log: upsd.c,v $
* Revision 1.4 86/11/19 15:21:52 scooter
* Changed error severity level from ERR to INFO
*
* Revision 1.3 86/09/19 18:53:37 scooter
* Added -i option for mail specification.
* Also added syslog stuff.
*
* Revision 1.2 85/08/21 22:28:11 scooter
* Release revision: added more complete RCS headers.
*
*
*/
#ifdef amigados
#include "sys.h"
#endif
#include <stdio.h>
#include <pwd.h>
#include <grp.h>
#include <sys/file.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <syslog.h>
#include <string.h>
#ifndef amigados
long atol();
int atoi();
#else
#include <popen.h>
#include "upsd_protos.h"
#endif
char buffer[BUFSIZ*5]; /* character input buffer */
char file_name[BUFSIZ]; /* file name */
char file_path[BUFSIZ]; /* full path to destination */
#ifdef amigados
char file_path2[BUFSIZ]; /* full path to destination */
#endif
char user_name[BUFSIZ]; /* Receiver name */
char from_name[BUFSIZ]; /* Sender name */
char full_name[BUFSIZ]; /* Full name of sender */
char file_list[BUFSIZ]; /* List of all files */
long file_size; /* number of bytes in file */
int file_mode; /* mode of the file */
char mail_message[BUFSIZ*4]; /* mail message */
int mcount; /* number of characters in mail buffer */
int fid; /* File descriptor for destination */
#ifdef DEBUG
int debugflag = 1; /* Debug flag */
#else
int debugflag = 0; /* Debug flag */
#endif
#ifdef amigados
extern int server_socket;
extern int errno;
#endif
int fdin, fdout;
main(argc, argv)
int argc;
char **argv;
{
char *ptr,*tptr,*mptr;
int f, i, file;
struct sockaddr_in sin;
struct hostent *peer;
struct passwd *pwent;
int retries = 10;
#ifndef amigados
fdinout = 0;
fdout = 1;
#else
fdin = server_socket + S_MAXFH; /* s_socket magic */
fdout = fdin;
#endif
openlog("upsd",LOG_ODELAY,LOG_DAEMON);
syslog(LOG_DEBUG, "started - test");
if(argc>1 && !strcmp(argv[1], "-d") )
debugflag++;
if (debugflag)
syslog(LOG_DEBUG,"started");
i = sizeof (sin);
if (getpeername(fdin, &sin, &i) < 0)
syslog(LOG_ERR,"getpeername failed: %m");
if (debugflag)
syslog(LOG_DEBUG,"Calling gethostbyaddr");
peer = gethostbyaddr((char *)&sin.sin_addr,
sizeof(sin.sin_addr),sin.sin_family);
buffer[0] = '\0';
file_list[0] = '\0';
if (debugflag)
syslog(LOG_DEBUG,"Reading first buffer");
read(fdin, buffer, BUFSIZ*5); /* fetch receiver and sender names */
if (debugflag)
syslog(LOG_DEBUG,"receiver/sender/message: %s",buffer);
ptr = buffer;
while (*ptr != '\n')
ptr++;
*ptr++ = NULL;
strcpy(user_name, buffer); /* save receiver name */
tptr = ptr;
while (*tptr != '\n')
tptr++;
*tptr++ = NULL;
strcpy(from_name, ptr); /* save sender name */
mptr = tptr;
while ((*mptr != '\n') && (*mptr != '\0'))
mptr++;
*mptr++ = NULL;
strcpy (full_name, tptr); /* save sender's full name */
strcpy (mail_message, mptr); /* save the mail message */
/*
* Check for a valid user
*/
#ifdef amigados
if(1)
{
char *env;
#if 1 /* deactivate this to become schizophrenic :-) */
env = getenv("UPS_USERS");
if(!env)
{
error("Receiver name", "UPS_USERS not set");
exit(1);
}
{
int l = strlen(user_name);
char *s;
int legal=0;
while(s = strstr(env, user_name))
{
if(((s == env) || (*(s-1) == ':'))
&& ((s[l] == '\0') || (s[l] == ':')))
{
legal = 1;
break;
}
}
if(!legal)
{
error("Receiver name, Not in UPS_USERS:", user_name);
exit(1);
}
}
#endif
/* fake password entry */
pwent = malloc(sizeof(struct passwd));
memset(pwent, 0, sizeof(struct passwd));
pwent->pw_passwd = strdup("");
pwent->pw_shell = strdup("");
pwent->pw_name = strdup(user_name);
pwent->pw_gecos = strdup("Amiga OS Power User");
ack();
}
#else
if ((pwent = getpwnam(user_name)))
ack();
else
{
error("Receiver name","No such person");
exit(1);
}
#endif
mcount = strlen (mail_message);
if (debugflag)
syslog(LOG_DEBUG,"mail message (%d chars):\n %s", mcount, mail_message);
for (file = 0 ;;)
{
#ifdef amigados
int cnt;
#endif
if ((cnt = read(fdin, buffer, BUFSIZ)) <= 0) {
error("file name","premature EOF or file read error");
if (debugflag)
syslog(LOG_DEBUG,"cnt = %d, errno = %d", cnt, errno);
#ifdef amigados
if(--retries)
{
error("file name", "too many retries");
break;
}
continue;
}
#ifdef amigados
retries = 10;
#endif
strcpy(file_name,buffer);
if (debugflag)
syslog(LOG_DEBUG,"File name:%s",file_name);
/*
* Are we done??
*/
if (!strncmp(file_name,"-Done-",6)) break;
if ( (fid = opendest(user_name,file_name,
pwent->pw_uid,pwent->pw_gid)) <= 0 )
{
continue;
}
ack();
if (read(fdin, buffer, BUFSIZ) <= 0) {
error("file size","premature EOF or file read error");
if (debugflag)
syslog(LOG_DEBUG,"errno = %d", errno);
continue;
}
file_size = atol(buffer); /* get number of bytes */
ack();
copyfile(&file);
if (read(fdin, buffer, BUFSIZ) <= 0) {
error("file mode","premature EOF or file read error");
continue;
}
file_mode = atoi(buffer); /* get the file mode */
#ifndef amigados
file_mode &= 0700; /* Strip the low order modes */
#else
/* use unix style modes for transmission to be compatible with
unix version, we will loose amiga specific bits */
{
int ami_mode = 8; /* read per default on */
if(file_mode & 0444)
ami_mode |= 8;
if(file_mode & 0222)
ami_mode |= 4 | 1;
if(file_mode & 0111)
ami_mode |= 2;
file_mode = ami_mode;
}
#endif
if (chmod(file_path,file_mode)) {
error("file mode","chmod failed");
continue;
}
ack();
#ifndef amigados
chown(file_path,pwent->pw_uid,pwent->pw_gid);
#endif
}
ack();
if (file)
sendmail(from_name,full_name,peer->h_name,
user_name,file_list,file++,mail_message,mcount);
}
/*
copyfile
copyfile will copy file_size many bytes from stdin to a temporarily created
file. The filename will be passed back via buffer.
*/
copyfile(file)
int *file;
{
long cnt; /* file size counter */
int i;
cnt = file_size; /* count down input bytes */
while (cnt > 0) {
i = read(fdin, buffer, BUFSIZ);
write(fid, buffer, i);
cnt -= i;
}
close(fid);
ack();
sprintf(buffer,"%-15s",file_name);
if (*file%4)
strcat(file_list," ");
else
strcat(file_list,"\n\t");
(*file)++;
strcat(file_list,buffer);
}
/*
error(option, string)
char *option, *string;
This routine is called when some error condition has been encountered.
option contains an identifier message, while string contains the actual
error message. Before message is printed, a non-null character is output
first, then the string error message.
*/
error(option, string)
char *option, *string;
{
char buf[BUFSIZ];
buf[0] = 1;
write(fdout, buf, 1); /* nak */
sprintf(buf, "upsd: %s: %s\n", option, string);
write(fdout, buf, strlen(buf)+1);
syslog(LOG_INFO,"error - %s",buf);
}
/*
* ack()
* This routine is called to return an OK to the remote host.
*/
ack()
{
buffer[0] = 0;
write(fdout,buffer,1);
}
/*
* opendest(name,file)
* char *name,*file;
*
* Open the destination file "file" in UPSDIR/user, creating the
* file if necessary.
*/
int
opendest(name,file,uid,gid)
char *name,*file;
int uid,gid;
{
int ret;
#ifndef amigados
sprintf(file_path,"%s/%s",UPSDIR,name); /* Form path to directory */
#else
strmfp(file_path,UPSDIR,name); /* Form path to directory */
#endif
if (access(file_path,F_OK) == (-1))
{
#ifndef amigados
mkdir(file_path,0700);
chown(file_path,uid,gid);
#else
mkdir(file_path);
#endif
}
#ifndef amigados
sprintf(file_path,"%s/%s/%s",UPSDIR,name,file);
#else
strcpy(file_path2, file_path);
sprintf(file_path,"%s/%s",file_path2,file);
#endif
if (!access(file_path,F_OK))
{
error("file creation","A file by that name has already been sent to that user.");
return(0);
} else {
#ifndef amigados
ret = open(file_path,O_WRONLY|O_CREAT,0600);
#else
ret = open(file_path,O_WRONLY|O_CREAT);
#endif
if (ret <= 0)
{
sprintf(buffer,"unable to open destination file: %s",
file_path);
error("file open",buffer);
return(0);
}
return(ret);
}
}
/*
* sendmail(from,full,from_host,to,list,mess,count)
* char *from,*full,*to,*from_host,*list,*mess;
* int count;
*
* This routine sends mail to the destination user to inform
* them that ups files are awaiting them.
*/
sendmail(from,full,from_host,to,list,file,mess,count)
char *from,*full,*to,*from_host,*list,*mess;
int file,count;
{
FILE *send,*popen();
static char myhost[BUFSIZ];
#ifndef amigados
gethostname(myhost,BUFSIZ);
#else
if(1)
{
char *env;
env = getenv("HOSTNAME");
if(env)
strncpy(myhost, env, BUFSIZ);
else
strncpy(myhost, "HOSTNAME not set", BUFSIZ);
}
#endif
sprintf(buffer,"%s -f%s@%s -F\"%s\" -t",SENDMAIL,from,from_host,full);
if(debugflag)
syslog(LOG_DEBUG,"sendmail\n%s",buffer);
send = popen(buffer,"w");
fprintf(send,"To: %s@%s\n",to,myhost);
if(debugflag)
syslog(LOG_DEBUG,"To: %s@%s",to,myhost);
fprintf(send,"Subject: UPS delivery\n");
if (file > 1)
strcpy(buffer,"files");
else
strcpy(buffer,"file");
fprintf(send,"I have sent you the following %s using ups:\n",buffer);
fprintf(send,"%s\n\n",list);
if (file > 1)
strcpy(buffer,"these files");
else
strcpy(buffer,"this file");
fprintf(send,"To retrieve %s, use the ups command.\n\n\n",buffer);
if (count)
fprintf(send,"%s\n",mess);
else
fprintf(send,"\n\n\n\n---ups\n");
pclose(send);
}